# -*- coding: utf-8 -*-
from time import mktime
from datetime import datetime
from datetime import timedelta
from hashlib import md5
from os import makedirs
from os.path import exists
from tkinter import END
from inspect import isclass
from ctypes import c_long
from ctypes import py_object
from ctypes import pythonapi
from logging import DEBUG
from logging import INFO
from logging import WARNING
from logging import ERROR
from logging import CRITICAL
from logging import getLogger
from logging import FileHandler
from logging import basicConfig
from SuperEmailSender.settings import LOG_LEVEL
from SuperEmailSender.settings import LOG_FILE_MODE
from SuperEmailSender.settings import LOG_DIR
from SuperEmailSender.settings import LOG_FILE


class TextFileHandler(FileHandler):
    text_log = None

    def __init__(self, *args, **kwargs):
        super(TextFileHandler, self).__init__(*args, **kwargs)

    def emit(self, record):
        if self.text_log is not None:
            msg = self.format(record)
            self.text_log.insert(END, msg)
            self.text_log.insert(END, self.terminator)
            self.text_log.see(END)
        FileHandler.emit(self, record)


class BaseClass(object):
    name = 'BaseClass'
    log_level = LOG_LEVEL
    text_log = None

    def __init__(self, *args, **kwargs):
        super(BaseClass, self).__init__(*args, **kwargs)
        self._level = {'DEBUG': DEBUG, 'INFO': INFO, 'WARNING': WARNING, 'ERROR': ERROR, 'CRITICAL': CRITICAL}

    @property
    def logger(self):
        try:
            if not exists(LOG_DIR): makedirs(LOG_DIR)
        except Exception as e: pass
        level = self._level[self.log_level]
        for i in ['asyncio', 'concurrent.futures']: getLogger(i).propagate = False
        handlers = TextFileHandler(filename=LOG_FILE, mode=LOG_FILE_MODE, encoding='utf-8')
        TextFileHandler.text_log = self.text_log
        kwargs = {
            'level': level, 'handlers': [handlers], 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        }
        basicConfig(**kwargs)
        logger = getLogger(self.name)
        return logger

    def md5sum(self, src):
        m = md5()
        m.update(str(src).encode('utf-8'))
        return m.hexdigest()

    def get_n_date(self, days=0, hours=0, minutes=0, seconds=0):
        dates = datetime.now() + timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
        un_time = mktime(dates.timetuple())
        return un_time

    def page_iter(self, source, per_list_len=10):
        list_of_group = []
        per_list = list(source.items()) if type(source) == dict else source if type(source) == str else list(source)
        if per_list:
            d = (iter(per_list),) * per_list_len
            list_of_group = list(zip(*d))
            count = len(per_list) % per_list_len
            if count: list_of_group.append(tuple(per_list[-count:]))
        return list_of_group

    def _async_raise(self, tid, exctype):
        tid = c_long(tid)
        if not isclass(exctype):
            exctype = type(exctype)
        res = pythonapi.PyThreadState_SetAsyncExc(tid, py_object(exctype))
        if res == 0:
            raise ValueError('invalid thread id')
        elif res != 1:
            pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError('PyThreadState_SetAsyncExc failed')

